-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Enqueue only required frontend styles - V1 #6166
[WIP] Enqueue only required frontend styles - V1 #6166
Conversation
Added a class "WP_Parsed_Block_Types_Registry" to manage the storage of block types parsed from the HTML (while stripping block comments)
Core block types parsed from the HTML may not contain 'core/'. Added a function gutenberg_prefix_core_namespace_if_not_found() to do the same.
…required-frontend-styles
…required-frontend-styles
…required-frontend-styles
This is work in progress and will be completely overhauled. Just committing it so that I don't lose it.
…required-frontend-styles
…e enqueued The new logic checks if the current requested web page is in the frontend. And if it's page or a post. If the answer is yes to both, it only enqueues styles for blocks which are present in the post/page.
…required-frontend-styles
…required-frontend-styles
Hey @kanishkdudeja I checked your work on this PR and on #5445 and I think that my goal on #5740 might be aligned with what you're doing here. Long story short, I think we could leverage the framework you're working for bundling frontend assets for blocks and also allow devs to add attribute based styles to be bundled into the final static css file that will be generated. What do you think? |
lib/blocks.php
Outdated
* @return string Name of the block type, prefixed by the core namespace if needed. | ||
*/ | ||
function gutenberg_prefix_core_namespace_if_not_found( $block_type ) { | ||
$block_type = trim( $block_type ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we expect leading or trailing whitespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will not expect leading/trailing whitespace from where the function is being called right now (gutenberg_process_block_comment()).
But this function can also be called as a library function from other functions in future. So, I thought it might be a good idea to trim the input since a normalized block type
cannot contain leading/trailing whitespace.
What do you think @aduth ?
lib/blocks.php
Outdated
* @param string $block_type Name of the block type. | ||
* @return string Name of the block type, prefixed by the core namespace if needed. | ||
*/ | ||
function gutenberg_prefix_core_namespace_if_not_found( $block_type ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could simplify / generalize the function name to reflect the fact that we want a normal/standard block type to work with:
gutenberg_normalize_block_type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I also thought about this. Couldn't think of a proper name then.
Have renamed it now.
lib/blocks.php
Outdated
// Only process the block comment if it's not a closing tag for a block. If it's a closing tag, we can just return. | ||
if ( preg_match( '/\/wp:/m', $block_comment ) !== 1 ) { | ||
|
||
$match = Array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to explicitly create a variable reference for preg_match
to assign into. This line could be removed altogether and still work just as well.
Aside: I'd encourage lowercase array()
. Confused me for a moment as I'm not used to seeing it this way, I thought it was some class special constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Removed the line altogether.
lib/blocks.php
Outdated
|
||
$match = Array(); | ||
|
||
preg_match( '/wp:(.*?)\s+/m', $block_comment, $match); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coding standards: Space before closing parenthesis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. This has been resolved.
lib/blocks.php
Outdated
* and so on. | ||
* @return string Returns an empty string to preg_replace_callback() for each of the block comments | ||
*/ | ||
function gutenberg_process_block_comment( $matches ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an aside, might be worth tracking conversation at #5967, since at some point we may want to re-introduce a grammar for block rendering which doesn't rely as much on regular expressions. I think this is fine given the current implementation though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I'll be tracking the conversation at #5967 now :)
lib/client-assets.php
Outdated
$is_editor = ( 'enqueue_block_editor_assets' === current_action() ); | ||
$is_frontend = ! $is_editor; | ||
|
||
$is_post_or_page = is_single() || is_page(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we just want to use is_singular
here? Or are we intentionally excluding attachment type?
https://developer.wordpress.org/reference/functions/is_singular/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original intention was to exclude attachment type. But it turns out is_single() returns true for attachment types as well.
Thanks for pointing this out. Have replaced this with: is_singular( array( 'post', 'page') )
lib/client-assets.php
Outdated
@@ -770,10 +780,52 @@ function gutenberg_enqueue_registered_block_scripts_and_styles() { | |||
wp_enqueue_script( $block_type->editor_script ); | |||
} | |||
} | |||
|
|||
if ( $enqueue_only_required_styles ) { | |||
add_action( 'the_content', 'enqueue_required_frontend_block_styles', 10 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Priority 10
is default, so can be omitted altogether as an argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'd mentioned wanting to support other plugins which modify the_content
to revise blocks. Does that mean enqueueing needs to occur at a later priority (higher value)? What about the parsing to determine which blocks are present in content? Similarly later? Currently at 9
, if a plugin would modify content at the default priority, I don't think WP_Parsed_Block_Types_Registry
would reflect those modifications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Thanks for pointing this out. I'm sorry this completely skipped my mind.
Now, gutenberg_process_block_comments
runs with PHP_INT_MAX - 1
priority and enqueue_required_frontend_block_styles
runs with PHP_INT_MAX
priority since front-end styles can be enqueued once block types are parsed and saved in the registry.
lib/client-assets.php
Outdated
if ( ! isset( $block_type ) ) { | ||
// Log the error here | ||
} else { | ||
if ( isset( $block_type->style ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Collapse into elseif
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. This has been resolved.
lib/client-assets.php
Outdated
$block_type = $all_block_types_registry->get_registered( $block_type_name ); | ||
|
||
if ( ! isset( $block_type ) ) { | ||
// Log the error here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you propose to log it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have logged it using trigger_error
in the latest commit.
This function will do the following things if WP_DEBUG is set as true:
- Print it in wp-content/debug.log file (if configured using WP_DEBUG_LOG).
- Will show it as a notice on the post.
If WP_DEBUG is set as false (by default), it won't print the log anywhere.
lib/client-assets.php
Outdated
// Log the error here | ||
} else { | ||
if ( isset( $block_type->style ) ) { | ||
wp_enqueue_style( $block_type->style ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So because we enqueue in the_content
, when exactly does the script get output? As part of late style printing in wp_footer
? Would that trigger a flash of unstyled content for the block since the markup of the block is output before its stylesheet? If so, could we overcome this by forcing the output of stylesheets right here, before the content (echo immediately) ?
Broad thoughts I have are:
|
Renamed gutenberg_prefix_core_namespace_if_not_found() to gutenberg_normalize_block_type() Removed '$match = Array()' since we don't need to declare a variable for preg_match() Fixed syntax to suit coding standards
…blocks Our rendering algorithm for dynamic blocks was stripping block comments after rendering those dynamic blocks. Disabled that functionality since block comments are needed to find out block types present in the page later.
…required-frontend-styles
get_last_error() function in Block Type Validator was referencing $errors as a local variable, whereas it should have referenced it as a class variable. Have fixed it in this commit.
Removed _doing_it_wrong notices from Block Type Validator class since the same are being called in the caller
…required-frontend-styles
…ts and enqueueing frontend styles Earlier, functions for stripping block comments and enqueueing frontend styles were given 9 and 10 priority respectively. This didn't work well since plugins might append more blocks to content (through filters at higher priority). Therefore, have assigned PHP_INT_MAX - 1 and PHP_INT_MAX priority to these so that these can be run as late as possible
Thanks for the elaborate and critical code review @aduth.
The WP_Parsed_Block_Registry serves 2 purposes here:
Yes, I felt the same. But we're already using similar regular expressions to parse As you suggested, I'm following the conversation on #5967 but do let me know if you feel we should use the
I don't think we will. That is a possibility in #6200 (V2). Since we are enqueuing required styles in the |
…f it's not registered
…required-frontend-styles
A comment describing the priority for a filter has now been moved to just above the add_filter() function so that it's more intuitive while reading.
Earlier, we were parsing block types from the HTML and saving them to the registry even for pages like category / archive pages (which contain multiple posts). Have disabled this functionality for such pages now since the registry is only needed for intelligent enqueueing of assets (which is needed for single post / page types as of now).
This pull request appears to have languished and will not be easily reconciled with master. Please feel free to reopen and rebase against the current master, or open a new pull request. |
This PR is a proof of concept for #5445. It only enqueues front-end styles for
block types
present in the current page/post.Dependencies
core blocks
aren't registered on server side (as of now, in master), it depends on [WIP] Update/build individual blocks #6087 to be merged first.Version 1 (enqueues styles inside
<body>
)This branch hooks a filter on
the_content
to getblock types
present in the page while stripping block comments from the HTML.Since filters hooked to
the_content
are executed much later in the lifecycle (after actions hooked towp_enqueue_scripts
are executed), the stylesheets are being enqueued in the<body>
section.Version 2 (enqueues styles inside
<head>
)#6200 reads the current post's content on the
wp_enqueue_scripts
action (much earlier thanthe_content
). Therefore, that enables us to be able to enqueue required styles inside the<head>
section.An issue with that approach is that if a plugin adds a
core block
using a filter onthe_content
later, our code won't be able to enqueue styles for thatblock type
since we would have read the post's content much earlier. Maybe we can try re-parsing the post's content to enqueue styles for anyremaining block types
after all filters onthe_content
have executed.To Do